#ifndef UpdateDesc_HPP
#define UpdateDesc_HPP

//#include "FileItem.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <list>
#include <string>
#include <fstream>
#include <errno.h>
#include <iostream>

#include "rapidxml.hpp"
#include "rapidxml_utils.hpp"
#include "rapidxml_print.hpp"

using namespace rapidxml;

class Description
{
public:
    string CurrentVersion;
    string PreviousVersion;
    string Platform;
    string URI;
    string Hash;
};

class FileItem
{
public:
    string Path;
    string URI;
    string Size;
    string Hash;
    string Operation;
    string Permissions;
    FileItem() {}
    ~FileItem() {}
};

class UpdateDesc
{

private:

public:

    Description Description;
    list<FileItem> FileItems;
    string UriPrefix;
    string PreUpdate;
    string PostUpdate;

    UpdateDesc() {}

    ~UpdateDesc() {}

    void AddDesc(const string &CurrentVersion, const string &PreviousVersion, const string &Platform, const string &URI)
    {
        Description.CurrentVersion = CurrentVersion;
        Description.PreviousVersion = PreviousVersion;
        Description.Platform = Platform;
        Description.URI = URI;
    }

    void AddFileItem(FileItem &fi)
    {
        FileItems.push_back(fi);
    }

    void AddFileItem(const string &Path, const string &URI, const string &Size, const string &Hash, const string &Operation, const string &Permissions)
    {
        FileItem fi;
        fi.Path = Path;
        fi.URI = URI;
        fi.Size = Size;
        fi.Hash = Hash;
        fi.Operation = Operation;
        fi.Permissions = Permissions;
        FileItems.push_back(fi);
    }

    int Write2XMLFile(const char *file)
    {
        xml_document<> doc;
        xml_node<>* rot = doc.allocate_node(rapidxml::node_pi, doc.allocate_string("xml version='1.0' encoding='utf-8'"));
        doc.append_node(rot);
        xml_node<>* xPearUpdate = doc.allocate_node(node_element, "PearUpdate", NULL);
        doc.append_node(xPearUpdate);

        xml_node<>* xDescription = doc.allocate_node(node_element, "Description", NULL);
        xDescription->append_node(doc.allocate_node(node_element, "CurrentVersion", Description.CurrentVersion.c_str()));
        xDescription->append_node(doc.allocate_node(node_element, "PreviousVersion", Description.PreviousVersion.c_str()));
        xDescription->append_node(doc.allocate_node(node_element, "Platform", Description.Platform.c_str()));
        xDescription->append_node(doc.allocate_node(node_element, "URI", Description.URI.c_str()));
        xDescription->append_node(doc.allocate_node(node_element, "Hash", Description.Hash.c_str()));
        xPearUpdate->append_node(xDescription);

        xml_node<>* xPreUpdate = doc.allocate_node(node_element, "PreUpdate", NULL);
        xPreUpdate->append_node(doc.allocate_node(node_cdata, "PreUpdate", PreUpdate.c_str()));
        xPearUpdate->append_node(xPreUpdate);

        xml_node<>* xUpdate = doc.allocate_node(node_element, "Update", NULL);
        list<FileItem>::iterator it;
        for(it = FileItems.begin(); it != FileItems.end(); ++it)
        {
            xml_node<>* xFileItem = doc.allocate_node(node_element, "File", NULL);
            xFileItem->append_node(doc.allocate_node(node_element, "Path", it->Path.c_str()));
            xFileItem->append_node(doc.allocate_node(node_element, "URI", it->URI.c_str()));
            xFileItem->append_node(doc.allocate_node(node_element, "Size", it->Size.c_str()));
            xFileItem->append_node(doc.allocate_node(node_element, "Hash", it->Hash.c_str()));
            xFileItem->append_node(doc.allocate_node(node_element, "Operation", it->Operation.c_str()));
            xFileItem->append_node(doc.allocate_node(node_element, "Permissions", it->Permissions.c_str()));
            xUpdate->append_node(xFileItem);
        }
        xPearUpdate->append_node(xUpdate);

        xml_node<>* xPostUpdate = doc.allocate_node(node_element, "PostUpdate", NULL);
        xPostUpdate->append_node(doc.allocate_node(node_cdata, "PostUpdate", PostUpdate.c_str()));
        xPearUpdate->append_node(xPostUpdate);

        std::string text;
        rapidxml::print(std::back_inserter(text), doc, 0);

        std::ofstream out(file);
        out << doc;
    }
};

#endif // UpdateDesc_HPP
